package com.zhuzi.component;

import cn.hutool.core.util.StrUtil;
import com.google.common.base.Splitter;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.util.concurrent.RateLimiter;
import com.zhuzi.utils.HttpClientUtils;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author zhuzi
 * 2023/7/8 16:30
 * 微信提醒
 */
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class WeixinComponent {
    /**
     * 普通消息
     */
    public static ListMultimap<String, LimitItem> multiMap = ArrayListMultimap.create();

    @Resource(name = "threadPool")
    ExecutorService threadPool;
    @Value("${wx.newgn}")
    private String wgnewGn;

    @PostConstruct
    public void init() {
        //分割字符串,定义多个群使用
        constructMap(wgnewGn, "#", "|", multiMap);
    }

    /**
     * 构造限流RateLimiter
     *
     * @param str      str
     * @param key      关键
     * @param splitStr str分割
     * @param multiMap 多值map
     */
    public void constructMap(String str, String key, String splitStr, ListMultimap<String, LimitItem> multiMap) {
        Map<String, String> split = Splitter.on(",").omitEmptyStrings().trimResults().withKeyValueSeparator(key).split(str);
        split.forEach((k, v) -> {
            List<LimitItem> collect = StrUtil.split(v, splitStr, true, true).stream().map(strItem -> new LimitItem().setId(strItem)).collect(Collectors.toList());
            multiMap.putAll(k, collect);
        });
    }

    public void sendHint(String content) {
        multiMap.keySet().forEach(k -> {
            //异步执行,否则多个群发送,会按顺序一个个群发送。
            threadPool.execute(() -> {
                String url = getRateUrl(multiMap.get(k));
                HttpClientUtils.httpPost(content, url);
            });
        });
    }

    public String getRateUrl(Collection<LimitItem> limitList) {
        while (true) {
            for (LimitItem item : limitList) {
                if (item.getRateLimiter().tryAcquire(100, TimeUnit.MILLISECONDS)) {
                    return item.getId();
                }
            }
        }
    }

    /**
     * 限流
     *
     * @author zhuzi
     * @date 2023/07/08
     */
    @Data
    @Accessors(chain = true)
    private static class LimitItem {
        /**
         * id
         */
        private String id;
        /**
         * 速度限制器
         */
        private RateLimiter rateLimiter = RateLimiter.create(1.0 / 3.5);
    }
}
